#pragma once

#include <cftc/reflect/object.h>

namespace cs
{

	class MFVec3 : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		float x = 0.0f;
		float y = 0.0f;
		float z = 0.0f;
	};

	class MFInventory : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		unsigned char inventory_type = 0;
		unsigned int displayer_info_id = 0;
	};

	class MFPlayerInfo : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		unsigned long long guid = 0;
		std::string name;
		unsigned char race = 0;
		unsigned char class_ = 0;
		unsigned char gender = 0;
		unsigned char skin = 0;
		unsigned char face = 0;
		unsigned char hair_style = 0;
		unsigned char hair_color = 0;
		unsigned char facial_hair = 0;
		unsigned char level = 0;
		unsigned int zone = 0;
		unsigned int map = 0;
		float x = 0;
		float y = 0;
		float z = 0;
		unsigned int guild_id = 0;
		unsigned int char_flags = 0;
		unsigned char first_login = 0;
		unsigned int pet_display_id = 0;
		unsigned int pet_level = 0;
		unsigned int pet_family = 0;

		std::vector<std::shared_ptr<MFInventory>> inventory_list;

		unsigned int reserve1 = 0;
		unsigned char reserve2 = 0;
	};

	class MFUpdateValues : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		std::vector<unsigned int> masks;
		std::vector<unsigned int> values;
	};
	
	class MFUpdateTypeValues : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	private:
		unsigned char update_type = UPDATETYPE_VALUES;
	public:
		unsigned long long guid = 0;
		MFUpdateValues values;
	};

	class MFPosition : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		float x = 0.0f;
		float y = 0.0f;
		float z = 0.0f;
		float o = 0.0f;
	};

	class MFMovementInfo : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		class MFMovementFlagOnTransport : public cftc::reflect::Object
		{
			CFT_DECLARE_REFLECT_CLASS();
		public:
			unsigned long long guid = 0;
			MFPosition pos;
			unsigned int time = 0;
		};

		class MFMovementFlagSwimming : public cftc::reflect::Object
		{
			CFT_DECLARE_REFLECT_CLASS();
		public:
			float pitch = 0.0f;
		};

		class MFMovementFlagFalling : public cftc::reflect::Object
		{
			CFT_DECLARE_REFLECT_CLASS();
		public:
			float velocity = 0.0f;
			float sinAngle = 0.0f;
			float cosAngle = 0.0f;
			float xyspeed = 0.0f;
		};
	public:
		unsigned int move_flags = 0;
		unsigned int time = 0;
		MFPosition pos;
		std::shared_ptr<MFMovementFlagOnTransport> flag_ontransport;
		std::shared_ptr<MFMovementFlagSwimming> flag_swimming;
		std::shared_ptr<unsigned int> fall_time;
		std::shared_ptr<MFMovementFlagFalling> flag_falling;
		std::shared_ptr<float> u_unk1;
	};

	class MFUpdateTypeCreateObject : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		class FlagLiving : public cftc::reflect::Object
		{
			CFT_DECLARE_REFLECT_CLASS();
		public:
			class FlagSpline : public cftc::reflect::Object
			{
				CFT_DECLARE_REFLECT_CLASS();
			public:
				unsigned int splineFlags = 0;
				std::shared_ptr<MFVec3> pos;
				std::shared_ptr<unsigned long long> target;
				std::shared_ptr<float> angle;
				int timePassed = 0;
				int Duration = 0;
				unsigned int id = 0;
				unsigned int nodes = 0;
				MFVec3 dest;
			};

		public:
			MFMovementInfo movement;
			float walk_speed = 0.0f;
			float run_speed = 0.0f;
			float swim_speed = 0.0f;
			float swim_back_speed = 0.0f;
			float turn_rate_speed = 0.0f;
			std::shared_ptr<FlagSpline> flag_spline;
		};

	private:
		unsigned char update_type = 0;

		unsigned long long guid = 0;
		unsigned char object_typeid = 0;
		unsigned char update_flags = 0;
		std::shared_ptr<FlagLiving> flag_living;
		std::shared_ptr<MFPosition> flag_pos;
		std::shared_ptr<unsigned int> flag_highguid;
		std::shared_ptr<unsigned int> flag_all;
		std::shared_ptr<unsigned long long> flag_fullguid;
		std::shared_ptr<unsigned int> flag_transport;
	};
	
	class MFUpdateTypeOutOfRangeObjects : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	private:
		unsigned char update_type = UPDATETYPE_OUT_OF_RANGE_OBJECTS;
	public:
		std::vector<unsigned long long> m_outOfRangeGUIDs;
	};

	class CMBootme
	{

	};

	class CMDbLookup
	{

	};

	class SMDBLookup
	{

	};

	class CMQueryObjectPosition
	{

	};

	class CMAuthSession : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		unsigned int built_number_client = 0;
		unsigned int unk2 = 0;
		std::string account;
		unsigned int client_seed;
		std::string digest;
	};

	class SMAuthResponse : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		unsigned char code = 0;
		unsigned int billing_time_remaining = 0;
		unsigned char billing_plan_flags = 0;
		unsigned int billing_time_rested = 0;
	};

	class CMCharEnum : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	};

	class SMCharEnum : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		std::vector<std::shared_ptr<MFPlayerInfo>> char_list;
	};

	class CMPlayerLogin : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		unsigned long long player_guid = 0;
	};

	class CMNameQuery
	{

	};

	class CMUpdateAccountData
	{

	};

	class CMSetActiveMover
	{

	};

	class SMLoginSettimespeed
	{

	};

	class SMNameQueryResponse
	{

	};

	class SMAuthChallenge : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		unsigned int seed = 0;
	};

	class SMUpdateObject : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		unsigned int seed = 0;
	};

	class SMLoginVerifyWorld : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		unsigned int map_id = 0;
		MFPosition pos;
	};

	class SMAccountDataTimes : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		std::vector<unsigned int> data;
	};

	class SMTrigggerClinematic : public cftc::reflect::Object
	{
		CFT_DECLARE_REFLECT_CLASS();
	public:
		unsigned int CinematicSequenceId = 0;
	};

}